/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package l1j.server.server.model;

import l1j.server.server.utils.Random;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.server.ActionCodes;
import l1j.server.server.GeneralThreadPool;
import l1j.server.server.model.L1Character;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_EffectLocation;
import l1j.server.server.serverpackets.S_UseAttackSkill;
import static l1j.server.server.model.skill.L1SkillId.*;

public class L1Chaser extends TimerTask {
	private static Logger _log = Logger.getLogger(L1Chaser.class.getName());

	private ScheduledFuture<?> _future = null;
	private int _timeCounter = 0;
	private final int _attr;
	private final int _gfxid;
	private final L1PcInstance _pc;
	private final L1Character _cha;

	public L1Chaser(L1PcInstance pc, L1Character cha, int attr, int gfxid) {
		_cha = cha;
		_pc = pc;
		_attr = attr;
		_gfxid = gfxid;
	}

	@Override
	public void run() {
		try {
			if (_cha == null || _cha.isDead()) {
				stop();
				return;
			}
			switch (_pc.getWeapon().getItem().getItemId()){
			case 265: case 266: case 267: case 268: //底比斯
			case 276: case 277: //提卡爾庫庫爾坎
			case 304: case 307: case 308: //隱藏 劍 ,爪, 鎖鏈劍
			case 305: case 306: case 309://隱藏 弓, 魔杖, 奇古獸
				attack();
				_timeCounter++;
				if (_timeCounter >= 3) {
					stop();
					return;
				}
				break;
			default:
				attack();
				stop();
				return;
			}
		} catch (Throwable e) {
			_log.log(Level.WARNING, e.getLocalizedMessage(), e);
		}
	}

	public void begin() {
		// 効果時間が8秒のため、4秒毎のスキルの場合処理時間を考慮すると実際には1回しか効果が現れない
		// よって開始時間を0.9秒後に設定しておく
		_future = GeneralThreadPool.getInstance().scheduleAtFixedRate(this, 0,
				1000);
	}

	public void stop() {
		if (_future != null) {
			_future.cancel(false);
		}
	}

	public void attack() {
		double damage = getDamage(_pc, _cha);
		if (_cha.getCurrentHp() - (int) damage <= 0 && _cha.getCurrentHp() != 1) {
			damage = _cha.getCurrentHp() - 1;
		} else if (_cha.getCurrentHp() == 1) {
			damage = 0;
		}
		S_EffectLocation packet = new S_EffectLocation(_cha.getX(),
				_cha.getY(), _gfxid);
		if (_pc.getWeapon() == null) { // 修正空手會出錯的問題
			damage = 0;
		}
		switch (_pc.getWeapon().getItem().getItemId()){
		case 265: case 266: case 267: case 268: //底比斯
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 7025);
			break;
		case 276: case 277: //提卡爾庫庫爾坎
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 7224);
			break;
		case 304: case 307: case 308: //隱藏 劍 ,爪, 鎖鏈劍
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 8150);
			break;
		case 305: case 306: case 309://隱藏 弓, 魔杖, 奇古獸
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 8152);
			break;
		case 121: // 冰之女王魔杖
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 1810);
			break;
		case 54: case 264: case 288:// 克特之劍 , 雷雨之劍, 天雷劍
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 10);
			break;
		case 58: // 死亡騎士劍
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 1811);
			break;
		case 203: //炎魔雙手劍
			packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 762);
			break;
			case 205: //  熾天使之弓
				//packet = new S_EffectLocation(_cha.getX(), _cha.getY(), 6288);
				int[] data = {ActionCodes.ACTION_Attack, 0, 6288, 6};
				S_UseAttackSkill packet1 = new S_UseAttackSkill(_pc, _cha.getId(), _cha.getX(), _cha.getY(), data, false);
				_pc.sendPackets(packet1);
				_pc.broadcastPacket(packet1);
				break;
		default: // 更換為其他武器 附加特效傷害歸零
			damage = 0;
			break;
		}
		_pc.sendPackets(packet);
		_pc.broadcastPacket(packet);
		if (_cha instanceof L1PcInstance) {
			L1PcInstance pc = (L1PcInstance) _cha;
			pc.sendPackets(new S_DoActionGFX(pc.getId(),
					ActionCodes.ACTION_Damage));
			pc.broadcastPacket(new S_DoActionGFX(pc.getId(),
					ActionCodes.ACTION_Damage));
			pc.receiveDamage(_pc, damage, false);
		} else if (_cha instanceof L1NpcInstance) {
			L1NpcInstance npc = (L1NpcInstance) _cha;
			npc.broadcastPacket(new S_DoActionGFX(npc.getId(),
					ActionCodes.ACTION_Damage));
			npc.receiveDamage(_pc, (int) damage);
		}
	}

	public double getDamage(L1PcInstance pc, L1Character cha) {
		double dmg = 0;
		int spByItem = pc.getSp() - pc.getTrueSp();
		int intel = pc.getInt();
		int charaIntelligence = pc.getInt() + spByItem - 12;
		double coefficientA = 1.0 + 3.0 / 32.0 * charaIntelligence;
		if (coefficientA < 1) {
			coefficientA = 1.0;
		}
		double coefficientB = 0;
		if (intel > 18) {
			coefficientB = (intel + 2.0) / intel;
		} else if (intel <= 12) {
			coefficientB = 12.0 * 0.065;
		} else {
			coefficientB = intel * 0.065;
		}
		double coefficientC = 0;
		switch (intel){
		
		}
		if (intel <= 12) {
			coefficientC = 6;
		} else if (intel >= 13 && intel <= 35){
			coefficientC = intel * 0.5 ;
		} else if (intel >= 36 && intel <= 75){
			coefficientC = intel * 0.6 ;
		}else {
			coefficientC = intel * 0.8;
		}
		dmg = (Random.nextInt(6) + 1 + 7) * coefficientA * coefficientB / 10.5
				* coefficientC * 2.0;
		dmg = L1WeaponSkill.calcDamageReduction(pc, cha, dmg, _attr);
		switch (pc.getWeapon().getItem().getItemId()){
		case 306:
			dmg += 100;
			break;
		case 121:
			dmg /= 2;
			break;
		case 264:
			dmg /= 2;
			break;
		case 58:
			dmg += pc.getStr();
			break;
		case 203:
			dmg += pc.getTrueSp();
			break;
		case 205:
			dmg /= 2;
			dmg += pc.getDex();
			break;
		}
		if (cha.hasSkillEffect(IMMUNE_TO_HARM)) {
			dmg /= 2.0;
		}
		return dmg;
	}

}
